﻿using IoTClient;
using IoTClient.Common.Helpers;
using MiniExcelLibs;
using Polly;
using Serilog;
using Sunny.UI;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ArcLightProtector.Controls
{
    public partial class Protector1Controller : BaseController
    {




        private List<SensorPointData> _baseList = new List<SensorPointData>();
        private List<SensorPointData> _remoteSignallingList = new List<SensorPointData>();
        private List<SensorPointData> _remoteMeasuringList = new List<SensorPointData>();
        private List<SensorPointData> _eventList = new List<SensorPointData>();
        private List<SensorPointData> _updateList = new List<SensorPointData>();

        public Protector1Controller()
        {
            ProtectorName = "导轨弧光保护";
            InitializeComponent();
        }



        public override void InitUI()
        {
            //遥信
            var tableFlayoutPanel1 = new TableLayoutPanel() { Dock = DockStyle.Fill };
            tableFlayoutPanel1.RowCount = (int)(Math.Ceiling(_baseList.Count(w => w.Name != "备用") * 1.0 / 3) + 1);
            tableFlayoutPanel1.ColumnCount = 3;

            for (int i = 0; i < tableFlayoutPanel1.ColumnCount; i++)
            {
                tableFlayoutPanel1.ColumnStyles.Add(new ColumnStyle() { SizeType = SizeType.Percent, Width = 33 });
            }

            for (int i = 0; i < tableFlayoutPanel1.RowCount; i++)
            {
                tableFlayoutPanel1.RowStyles.Add(new RowStyle() { SizeType = SizeType.Absolute, Height = 29 });
            }
            tableFlayoutPanel1.RowStyles.Add(new RowStyle { SizeType = SizeType.AutoSize });
            groupBox2.Controls.Add(tableFlayoutPanel1);


            foreach (var sensorPoint in _remoteSignallingList.Where(w => w.Name != "备用").ToList())
            {
                var control = new SensorPointControl() { PointData = sensorPoint };
                tableFlayoutPanel1.Controls.Add(control);
                AddControlDic(sensorPoint, control);
                _groupControls.Add(new GroupPointControl(sensorPoint.FuncName, sensorPoint.Address, control));
            }

            foreach (var item in _groupControls)
            {
                item.Control.OnSettingValueBefore += Item_OnSettingValueBefore;
                item.Control.OnSettingValueAfter += Item_OnSettingValueAfter;
            }

            //遥测
            var tableFlayoutPanel2 = new TableLayoutPanel() { Dock = DockStyle.Fill };
            tableFlayoutPanel2.RowCount = (int)(Math.Ceiling(_remoteMeasuringList.Count * 1.0 / 3) + 1);
            tableFlayoutPanel2.ColumnCount = 3;

            for (int i = 0; i < tableFlayoutPanel1.ColumnCount; i++)
            {
                tableFlayoutPanel2.ColumnStyles.Add(new ColumnStyle() { SizeType = SizeType.Percent, Width = 33 });
            }

            for (int i = 0; i < tableFlayoutPanel2.RowCount; i++)
            {
                tableFlayoutPanel2.RowStyles.Add(new RowStyle() { SizeType = SizeType.Absolute, Height = 29 });
            }
            tableFlayoutPanel2.RowStyles.Add(new RowStyle { SizeType = SizeType.AutoSize });
            groupBox3.Controls.Add(tableFlayoutPanel2);


            foreach (var sensorPoint in _remoteMeasuringList)
            {
                var control = new SensorPointControl() { PointData = sensorPoint };
                tableFlayoutPanel2.Controls.Add(control);
                AddControlDic(sensorPoint, control);
                _groupControls.Add(new GroupPointControl(sensorPoint.FuncName, sensorPoint.Address, control));
            }

            //事件值
            var tableFlayoutPanel3 = new TableLayoutPanel() { Dock = DockStyle.Fill };
            tableFlayoutPanel3.RowCount = (int)(Math.Ceiling(_eventList.Count * 1.0 / 3) + 1);
            tableFlayoutPanel3.ColumnCount = 3;

            for (int i = 0; i < tableFlayoutPanel3.ColumnCount; i++)
            {
                tableFlayoutPanel3.ColumnStyles.Add(new ColumnStyle() { SizeType = SizeType.Percent, Width = 33 });
            }

            for (int i = 0; i < tableFlayoutPanel3.RowCount; i++)
            {
                tableFlayoutPanel3.RowStyles.Add(new RowStyle() { SizeType = SizeType.Absolute, Height = 29 });
            }
            tableFlayoutPanel3.RowStyles.Add(new RowStyle { SizeType = SizeType.AutoSize });
            groupBox4.Controls.Add(tableFlayoutPanel3);


            foreach (var sensorPoint in _eventList)
            {
                var control = new SensorPointControl() { PointData = sensorPoint };
                tableFlayoutPanel3.Controls.Add(control);
                AddControlDic(sensorPoint, control);
                _groupControls.Add(new GroupPointControl(sensorPoint.FuncName, sensorPoint.Address, control));
            }

            //电流定制修改
            var tableFlayoutPanel4 = new TableLayoutPanel() { Dock = DockStyle.Fill };
            tableFlayoutPanel4.RowCount = (int)(Math.Ceiling(_eventList.Count * 1.0 / 3) + 1);
            tableFlayoutPanel4.ColumnCount = 3;

            for (int i = 0; i < tableFlayoutPanel4.ColumnCount; i++)
            {
                tableFlayoutPanel4.ColumnStyles.Add(new ColumnStyle() { SizeType = SizeType.Percent, Width = 33 });
            }

            for (int i = 0; i < tableFlayoutPanel4.RowCount; i++)
            {
                tableFlayoutPanel4.RowStyles.Add(new RowStyle() { SizeType = SizeType.Absolute, Height = 29 });
            }
            tableFlayoutPanel4.RowStyles.Add(new RowStyle { SizeType = SizeType.AutoSize });
            groupBox5.Controls.Add(tableFlayoutPanel4);


            foreach (var sensorPoint in _updateList)
            {
                var control = new SensorPointControl() { PointData = sensorPoint };
                tableFlayoutPanel4.Controls.Add(control);
                AddControlDic(sensorPoint, control);
                _groupControls.Add(new GroupPointControl(sensorPoint.FuncName, sensorPoint.Address, control));
            }

            foreach (var kv in _groupControls)
            {
                kv.Control.ProtectorName = "导轨弧光保护";
            }
        }

        protected override void InitData()
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            Stream stream = assembly.GetManifestResourceStream("ArcLightProtector.1.xlsx");

            _remoteSignallingList = MiniExcel.Query<SensorPointData>(stream, "遥信").ToList()
                .Where(w => !string.IsNullOrEmpty(w.Name)).ToList();

            _remoteMeasuringList = MiniExcel.Query<SensorPointData>(stream, "遥测").ToList()
                .Where(w => !string.IsNullOrEmpty(w.Name)).ToList();


            _eventList = MiniExcel.Query<SensorPointData>(stream, "事件值").ToList()
    .Where(w => !string.IsNullOrEmpty(w.Name)).ToList();

            _updateList = MiniExcel.Query<SensorPointData>(stream, "电流定值修改").ToList()
                    .Where(w => !string.IsNullOrEmpty(w.Name)).ToList();


            _remoteSignallingList.ForEach(x => x.FuncName = "遥信");
            _remoteMeasuringList.ForEach(x => x.FuncName = "遥测");
            _eventList.ForEach(x => x.FuncName = "事件值");
            _updateList.ForEach(x => x.FuncName = "电流定值修改");


            _all.AddRange(_remoteSignallingList);
            _all.AddRange(_remoteMeasuringList);
            _all.AddRange(_eventList);
            _all.AddRange(_updateList);
            _all.ForEach(x =>
            {
                x.Address = Convert.ToUInt16(x.AddressHex, 16);
                if (!string.IsNullOrEmpty(x.MapInfo))
                {
                    x.MapDic = new Dictionary<string, string>();
                    var lines = x.MapInfo.Split('|');
                    foreach (var item in lines)
                    {
                        var arr = item.Split(':');
                        x.MapDic.Add(arr[0], arr[1]);
                    }
                }
            });
        }


        protected override void CollectDataCore()
        {

            ////事件
            var command = new byte[] { _slaveId, 0x0C };
            command = CRC16.GetCRC16(command);
            var result = SendPackageReliableWithRetry(command);

            if (result.IsSucceed && result.Value.Length > 15)
            {
                var segment = new ArraySegment<byte>(result.Value, 3, 15);
                var bytes = segment.Select(s =>
                {
                    var s1 = s.ToString("X");
                    return byte.Parse(s1);
                }).ToList();
                _eventList[0].Value = bytes[0] * 100 + bytes[1];
                _eventList[0].RawValue = bytes[0] * 100 + bytes[1];

                for (var i = 1; i < 7; i++)
                {
                    _eventList[i].Value = (ushort)bytes[i + 1];
                    _eventList[i].RawValue = (ushort)bytes[i + 1];
                }
                bytes = segment.ToList();
                for (var i = 7; i < _eventList.Count; i++)
                {
                    _eventList[i].Value = (ushort)bytes[i + 1];
                    _eventList[i].RawValue = (ushort)bytes[i + 1];
                }
            }
            //else
            //{
            //    _eventList.ForEach(x =>
            //    {
            //        x.Value = null;
            //        x.RawValue = null;
            //    });
            //}
            RefreshControlValue(_eventList);

            //遥信
            command = new byte[] { _slaveId, 0x02, 0, 0, 0, 0x40 };
            command = CRC16.GetCRC16(command);
            result = SendPackageReliableWithRetry(command);
            if (result.IsSucceed && result.Value.Length > 8)
            {
                var segment = new ArraySegment<byte>(result.Value, 3, 8);
                var bytes = segment.ToArray();
                var values = new List<ushort>();
                var bools = new BitArray(bytes);
                for (int i = 0; i < bools.Count; i++)
                {
                    values.Add((ushort)(bools[i] ? 1 : 0));
                }

                for (int i = 0; i < _remoteSignallingList.Count; i++)
                {
                    _remoteSignallingList[i].RawValue = values[i];
                    _remoteSignallingList[i].Value = values[i];
                }

            }
            else
            {
                _remoteSignallingList.ForEach(x =>
                {
                    x.RawValue = (ushort)0;
                    x.Value = (ushort)0;
                });
            }

            foreach (SensorPointData data in _remoteSignallingList)
            {
                if (_controlDic.ContainsKey(data)) _controlDic[data].RefreshValue();
            }

            //遥测
            command = _client.GetReadCommand("0", _slaveId, 4, 0x0D);
            command = CRC16.GetCRC16(command);
            result = SendPackageReliableWithRetry(command);
            if (result.IsSucceed && result.Value.Length > 6)
            {
                var segment = new ArraySegment<byte>(result.Value, 3, 6);
                var bytes = segment.ToArray();
                var values = GetUInt16s(bytes, 3);
                for (var i = 0; i < values.Count; i++)
                {
                    _remoteMeasuringList[i].Value = values[i] * 1.0 / 100;
                    _remoteMeasuringList[i].RawValue = values[i];
                }
            }
            else
            {
                _remoteMeasuringList.ForEach(x =>
                {
                    x.RawValue = null;
                    x.Value = null;
                });
            }
            RefreshControlValue(_remoteMeasuringList);



            //电流
            command = new byte[] { _slaveId, 0x22, 00, 00, 00, 01 };
            command = CRC16.GetCRC16(command);
            result = SendPackageReliableWithRetry(command);
            if (result.IsSucceed && result.Value.Length > 0)
            {
                var segment = new ArraySegment<byte>(result.Value, 6, 2);
                var value = GetUInt16(segment.ToArray());
                _updateList[0].Value = value * 1.0 / 100;
                _updateList[0].RawValue = value;
            }
            else
            {
                _updateList.ForEach(x =>
                {
                    x.RawValue = (ushort)0;
                    x.Value = (ushort)0;
                });
            }
            RefreshControlValue(_updateList);
        }

        /// <summary>
        /// 对时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {

            var now = DateTime.Now;
            var commandBytes = new List<byte>() { _slaveId, 10 };
            var times = new List<int>()
            {
                now.Second,now.Minute,now.Hour,now.Day,now.Month,now.Year-2000
            }.Select(s => (ushort)s).ToList();


            foreach (var t in times)
            {
                var bytes = BitConverter.GetBytes(t);
                commandBytes.Add(bytes[1]);
                commandBytes.Add(bytes[0]);
            }
            var command = commandBytes.ToArray();
            command = CRC16.GetCRC16(command);
            var result = SendPackageReliableWithRetry(command);

            if (result.IsSucceed && result.Value.Length > 0) MessageBox.Show($"对时成功 时间:{now:yy-MM-dd HH:MM:ss} !");
            else MessageBox.Show("设置失败!");

        }

        /// <summary>
        /// 复位
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {

            var command = new byte[] { _slaveId, 06, 00, 00, 00, 00 };
            command = CRC16.GetCRC16(command);
            var result = SendPackageReliableWithRetry(command);
            if (result.IsSucceed && result.Value != null) MessageBox.Show($"复位成功!");
            else MessageBox.Show("设置失败!");

        }


        /// <summary>
        /// 发送包,带重试
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        private Result<byte[]> SendPackageReliableWithRetry(byte[] command)
        {
            _resetEvent.WaitOne();
            var result = Policy.HandleResult<Result<byte[]>>(x => x.Value == null || x.Value.Length == 0)
                .WaitAndRetry(2, _ => TimeSpan.FromMilliseconds(150)).Execute(() =>
            {
                return _client.SendPackageReliable(command);
            });
            Log.Information(BitConverter.ToString(command) + " -> " + BitConverter.ToString(result.Value));
            return result;
        }
    }
}
